#!/usr/bin/env python

import os
import sys
import getopt
from ConfigParser import ConfigParser

import numpy as np
import numpy.ma as ma
import scikits.timeseries as ts

import pypus as pp


APP_NAME = 'pypus'
AUTHOR   = 'Wilson Freitas'
VERSION  = '0.5'
URL      = 'http://aboutwilson.net/pypus'
EMAIL    = 'wilson@aboutwilson.net'


class GetOptions(object):
    def __init__(self):
        self.long_options = ['help']
        self.options = 'hgyI:O:L:P:'
        self.generator = False
        self.data_loader_code = ''
        self.pypus_path = ''
        self.parse_options(sys.argv[1:])
    
    def parse_options(self, argv):
        try:
            opts, args = getopt.getopt(argv, self.options, self.long_options)
        except getopt.GetoptError:
            self.usage()
            sys.exit(1)
        for opt, val in opts:
            if opt == '-I':
                self.input_separator = val
            elif opt == '-O':
                self.output_separator = val
            elif opt == '-L':
                self.data_loader_code = val
            elif opt == '-P':
                self.pypus_path = val
            elif opt == '-g':
                self.generator = True
            elif opt in ['-h', '--help']:
                self.usage()
                sys.exit(0)
        try:
            self.code = args[0]
        except IndexError:
            self.usage()
            sys.exit(1)
        
        try:
            self.filename = args[1]
        except IndexError:
            self.filename = None
        else:
            if not os.path.isfile(self.filename):
                sys.stderr.write('Error: %s is not a valid file\n' % self.filename)
                self.usage()
                sys.exit(1)
    
    def usage(self):
        sys.stderr.write('''\
Usage: 
    %(prog)s [OPTION] [CODE] FILE
    %(prog)s [OPTION] [CODE] < FILE
Options:
    -Isep   input separator
    -Osep   output separator
    -Lcode  code for data loading
    -Ppath  specify pypus path
    -g      code generates data
    -h      help
''' % { 'prog': APP_NAME } )
    


def load_config_file():
    """docstring for options"""
    rc_filename = os.path.expanduser('~/.pypusrc')
    config = ConfigParser()
    if not os.path.isfile(rc_filename):        
        ini_filename = os.path.join(sys.prefix, 'config', 'pypus.ini')
        ini_file = open(ini_filename)
        rc_file = open(rc_filename, 'w')
        rc_file.write(ini_file.read())
        rc_file.close()
        ini_file.close()
    config.read([rc_filename])
    # pypus_home = os.path.expanduser(config.get('setup', 'pypus_home'))
    # if not os.path.isdir(pypus_home):
    #     os.mkdir(pypus_home)
    return config


def get_pypus_path(config):
    """docstring for pypus_path"""
    pypus_path = []
    for d in config.get('setup', 'pypus_path').split(':'):
        if d.startswith('~'):
            d = os.path.expanduser(d)
        d = os.path.join(d, 'pypus')
        if os.path.isdir(d):
            pypus_path.append(d)
    return pypus_path


def get_pypus_modules(config):
    pypus_path = get_pypus_path(config)
    pypus_modules = []
    for _dir in pypus_path:
        pypus_modules += [mod[:-3] for mod in os.listdir(_dir) if mod[-3:] == '.py']
    pypus_modules += config.get('setup', 'modules').split()
    return pypus_modules


def main():
    config = load_config_file()
    options = GetOptions()
    # pypus setup
    pypus_path = get_pypus_path(config)
    sys.path += pypus_path
    pypus_modules = get_pypus_modules(config)
    session = pp.Pypus(pypus_modules, config.items('macros'))
    if options.generator:
        R = session.execute(options.code)
    else:
        # handling input 
        input_file = sys.stdin
        if options.filename:
            input_file = options.filename
        if not options.data_loader_code == '':
            S = session.execute(options.data_loader_code, input_file)
        else:
            S = session.execute(config.get('setup', 'default_loader'), input_file)
        # execute pypus
        R = session.execute(options.code, S)
    if type(R) in (np.ndarray, np.core.defmatrix.matrix):
        np.savetxt(sys.stdout, R)
    elif ma.isMA(R):
        ts.tofile(R, sys.stdout)
    elif type(R) is float:
        sys.stdout.write('%.18e\n' % R)
    elif type(R) is int:
        sys.stdout.write('%d\n' % R)
    elif R is None:
        pass
    else:
        sys.stdout.write('%s\n' % str(R))



if __name__ == '__main__':
    main()

